#include "EditorLayer.h"
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <ImGui/imgui.h>
#include "KuaDu/Scene/SceneSerializer.h"
#include "KuaDu/Utils/PlatformUtils.h"
#include <ImGuizmo.h>
#include "KuaDu/Math/Math.h"

namespace KD {

	// 渲染时间统计
	template<typename Fn>
	class Timer
	{
	public:
		Timer(const char* name, Fn& func)
			: m_Name(name), m_Stoped(false), m_Func(func)
		{
			m_StartTimepoint = std::chrono::high_resolution_clock::now();
		}

		~Timer()
		{
			if (!m_Stoped)
				Stop();
		}

		void Stop()
		{
			auto endTimepoint = std::chrono::high_resolution_clock::now();

			long long start = std::chrono::time_point_cast<std::chrono::microseconds>(m_StartTimepoint).time_since_epoch().count();
			long long end = std::chrono::time_point_cast<std::chrono::microseconds>(endTimepoint).time_since_epoch().count();

			m_Stoped = true;

			float duration = (end - start) * 0.001f;
			m_Func({ m_Name, duration });
		}
	private:
		const char* m_Name;
		std::chrono::time_point<std::chrono::steady_clock> m_StartTimepoint;
		bool m_Stoped;
		Fn m_Func;
	};

#define PROFILE_SCOPE(name) Timer timer##__LINE__(name, [&](ProfileResult profileResult) { m_ProfileResults.push_back(profileResult); });

	EditorLayer::EditorLayer()
		: Layer("EditorLayer"), m_CameraController(1600.0f / 900.0f, true)
	{
	}

	// 装载
	void EditorLayer::OnAttach()
	{
		FramebufferSpecification fbSpec;
		fbSpec.Attachments = { FramebufferTextureFormat::RGBA8, FramebufferTextureFormat::RED_INTEGER, FramebufferTextureFormat::Depth };
		fbSpec.Width = 1600;
		fbSpec.Height = 900;
		// 创建帧缓冲
		m_Framebuffer = Framebuffer::Create(fbSpec);
		// 创建场景
		m_ActiveScene = CreateRef<Scene>();
		// 创建编辑相机
		m_EditorCamera = EditorCamera(30.0f, 10.778f, 0.1f, 1000.0f);
		// 设置场景层次面板上下文
		m_SceneHierarchyPanel.SetContext(m_ActiveScene);
	}

	// 卸载
	void EditorLayer::OnDetach()
	{}

	// 更新
	void EditorLayer::OnUpdate(TimeStep ts)
	{
		// 重置视口大小
		if(FramebufferSpecification spec = m_Framebuffer->GetSpecification();
			m_ViewportSize.x > 0.0f && m_ViewportSize.y > 0.0f &&
			(spec.Width != m_ViewportSize.x || spec.Height != m_ViewportSize.y))
		{
			m_Framebuffer->Resize((uint32_t)m_ViewportSize.x, (uint32_t)m_ViewportSize.y);
			m_CameraController.OnResize(m_ViewportSize.x, m_ViewportSize.y);
			m_EditorCamera.SetViewportSize(m_ViewportSize.x, m_ViewportSize.y);
			m_ActiveScene->OnViewportResize((uint32_t)m_ViewportSize.x, (uint32_t)m_ViewportSize.y);
		}

		{
			PROFILE_SCOPE("Rendering duration:")

			// 更新相机控制器
			if (m_ViewportFocused)
				m_CameraController.OnUpdate(ts);

			// 更新编辑相机
			m_EditorCamera.OnUpdate(ts);

			Renderer2D::ResetStats();

			m_Framebuffer->Bind(); 
			RenderCommand::SetClearColor({ 0.1f, 0.1f, 0.1f, 1 });
			RenderCommand::Clear();
			// 清除帧缓冲附件
			m_Framebuffer->ClearAttachment(1, -1);

			// 更新场景
			m_ActiveScene->OnUpdateEditor(ts, m_EditorCamera);
			
			m_Framebuffer->Unbind(); // 解邦帧缓冲
		}
	}

	// 事件系统
	void EditorLayer::OnEvent(Event& e)
	{
		m_CameraController.OnEvent(e);
		m_EditorCamera.OnEvent(e);

		EventDispatcher dispatcher(e);
		dispatcher.Dispatch<KeyPressedEvent>(KD_BIND_EVENT_FN(EditorLayer::OnKeyPressed));
		dispatcher.Dispatch<MouseButtonPressedEvent>(KD_BIND_EVENT_FN(EditorLayer::OnMouseButtonPressed));
	}

	// ImGui渲染
	void EditorLayer::OnImGuiRender()
	{
		static bool dockspaceOpen = true;
		static bool opt_fullscreen_persistant = true;
		bool opt_fullscreen = opt_fullscreen_persistant;
		static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;

		ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
		if (opt_fullscreen)
		{
			ImGuiViewport* viewport = ImGui::GetMainViewport();
			ImGui::SetNextWindowPos(viewport->Pos);
			ImGui::SetNextWindowSize(viewport->Size);
			ImGui::SetNextWindowViewport(viewport->ID);
			ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
			ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
			window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
			window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
		}

		if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
			window_flags |= ImGuiWindowFlags_NoBackground;

		ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
		ImGui::Begin("DockSpace Demo", &dockspaceOpen, window_flags); // DockSpace Demo
		ImGui::PopStyleVar();

		if (opt_fullscreen)
			ImGui::PopStyleVar(2);

		//DockSpace
		ImGuiIO& io = ImGui::GetIO();
		ImGuiStyle& style = ImGui::GetStyle();
		float minWinSizeX = style.WindowMinSize.x;
		style.WindowMinSize.x = 200.0f;
		if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
		{
			ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
			ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
		}
		style.WindowMinSize.x = minWinSizeX;
		// 菜单
		if (ImGui::BeginMenuBar())
		{
			if (ImGui::BeginMenu("File"))
			{
				if (ImGui::MenuItem("New", "Ctrl+N"))
					NewScene();

				if (ImGui::MenuItem("Open...", "Ctrl+O"))
					OpenScene();

				if (ImGui::MenuItem("Save As...", "Ctrl+Shift+S"))
					SaveSceneAs();

				if (ImGui::MenuItem("Exit")) Application::Get().Close();
				ImGui::EndMenu();
			}
			ImGui::EndMenuBar();
		}

		// 层次结构面板
		m_SceneHierarchyPanel.OnImGuiRender();

		// stats
		ImGui::Begin("Stats");
		// 选择的实体名称
		std::string name = "None";
		if (m_HoveredEntity)
			name = m_HoveredEntity.GetComponent<TagComponent>().Tag;
		ImGui::Text("m_HoveredEntity: %s", name.c_str());
		// 渲染统计
		auto stats = Renderer2D::GetStats();
		ImGui::Text("Render2D Stats:");
		ImGui::Text("DrawCalls: %d", stats.DrawCalls);
		ImGui::Text("QuadCount: %d", stats.QuadCount);
		ImGui::Text("VertexCount: %d", stats.GetTotalVertexCount());
		ImGui::Text("IndexCount: %d", stats.GetTotalIndexCount());

		// 性能分析
		for (auto& result : m_ProfileResults)
		{
			char label[50];
			strcpy_s(label, result.Name);
			strcat_s(label, " %.3fms");
			ImGui::Text(label, result.Time);
		}
		m_ProfileResults.clear();
		ImGui::End(); // stats

		// 视口
		ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 0, 0 });
		ImGui::Begin("Viewport"); // Viewport

		auto viewportOffset = ImGui::GetCursorPos();

		m_ViewportFocused = ImGui::IsWindowFocused();
		m_ViewportHovered = ImGui::IsWindowHovered();
		Application::Get().GetImGuiLayer()->BlockEvents(!m_ViewportFocused && !m_ViewportHovered);

		ImVec2 viewportPanelSize = ImGui::GetContentRegionAvail();

		m_ViewportSize = { viewportPanelSize.x, viewportPanelSize.y };
		// 转换ImTextureID
		uint32_t textureID = m_Framebuffer->GetColorAttachmentRendererID(1);
		KD_ASSERT(textureID, "错误处理：帧缓冲未正确初始化");// 检查纹理 ID 是否为有效值
		// 显示图像
		ImGui::Image(static_cast<ImU64>(textureID), ImVec2(m_ViewportSize.x, m_ViewportSize.y), ImVec2(0, 1), ImVec2(1, 0));
		auto windowSize = ImGui::GetWindowSize();
		ImVec2 minBound = ImGui::GetWindowPos();
		minBound.x += viewportOffset.x;
		minBound.y += viewportOffset.y;
		ImVec2 maxBound = { minBound.x + windowSize.x, minBound.y + windowSize.y };
		m_ViewportBounds[0] = { minBound.x, minBound.y };
		m_ViewportBounds[1] = { maxBound.x, maxBound.y };

		// 变换控件
		Entity slectedEntity = m_SceneHierarchyPanel.GetSelectedEntity();//获取选择的实体
		if (slectedEntity && m_GizmoType != -1)
		{
			ImGuizmo::SetOrthographic(false); // 设置透视相机
			ImGuizmo::SetDrawlist(); // 设置渲染列表
			float windowWidth = (float)ImGui::GetWindowWidth();
			float windowHeight = (float)ImGui::GetWindowHeight();
			ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, windowWidth, windowHeight); // 设置矩形
			// 实体运行时相机
			//auto cameraEntity = m_ActiveScene->GetPrimaryCameraEntity(); // 获取相机
			//const auto& camera = cameraEntity.GetComponent<CameraComponent>().Camera;
			//const glm::mat4& cameraProjection = camera.GetProjection(); // 相机变换矩阵
			//glm::mat4 cameraView = glm::inverse(cameraEntity.GetComponent<TransformComponent>().GetTransform());  // 相机视图(逆矩阵)
			
			// 编辑相机
			const glm::mat4& cameraProjection = m_EditorCamera.GetProjection(); // 相机变换矩阵
			glm::mat4 cameraView = m_EditorCamera.GetViewMatrix();

			// 实体变换矩阵
			auto& tc = selectedEntity.GetComponent<TransformComponent>();
			glm::mat4 transform = tc.GetTransform();

			bool snap = Input::IsKeyPressed(KEY::LeftControl);
			float snapValue = 0.5f;
			if (m_GizmoType == ImGuizmo::OPERATION::ROTATE)
				snapValue = 45.0f;

			float snapValues[3] = { snapValue, snapValue, snapValue };
			// 操作实体
			ImGuizmo::Manipulate(glm::value_ptr(cameraView), glm::value_ptr(cameraProjection),
				(ImGuizmo::OPERATION)m_GizmoType, ImGuizmo::LOCAL, glm::value_ptr(transform),
				nullptr, snap ? snapValues : nullptr);

			if (ImGuizmo::IsUsing())
			{
				glm::vec3 translation, rotation, scale;
				Math::DecomposeTransform(transform, translation, rotation, scale);
				glm::vec3 deltaRotation = rotation - tc.Rotation;
				tc.Translation = translation;
				tc.Rotation += deltaRotation;
				tc.Scale = scale;
			}
		}

		ImGui::End(); // Viewport
		ImGui::PopStyleVar();

		ImGui::End(); // DockSpace Demo
	}

	// 键盘事件
	bool EditorLayer::OnKeyPressed(KeyPressedEvent& e)
	{
		if (e.GetRepeatCount() > 0)
			return false;

		bool control = Input::IsKeyPressed(KEY::LeftControl) || Input::IsKeyPressed(KEY::RightControl);
		bool shift = Input::IsKeyPressed(KEY::LeftShift) || Input::IsKeyPressed(KEY::RightShift);

		switch (e.GetKeyCode())
		{
			case KEY::N:
				if (control) NewScene();
				break;
			case KEY::O:
				if (control) OpenScene();
				break;
			case KEY::S: 
				if (control && shift) SaveSceneAs();
				break;
			case KEY::Escape:
				Application::Get().Close();
				break;
			// Gizmos
			case KEY::Q:
				m_GizmoType = -1;
				break;
			case KEY::E:
				m_GizmoType = ImGuizmo::OPERATION::TRANSLATE;
				break;
			case KEY::R:
				m_GizmoType = ImGuizmo::OPERATION::ROTATE;
				break;
			case KEY::T:
				m_GizmoType = ImGuizmo::OPERATION::SCALE;
				break;
		}
	}

	// 鼠标点击事件
	bool EditorLayer::OnMouseButtonPressed(MouseButtonPressedEvent& e)
	{
		if (e.GetMouseButton() == Mouse::ButtonLeft && !ImGuizmo::IsOver() && !Input::IsKeyPressed(KEY::LeftAlt))
		{
			if (m_ViewportHovered)
				m_SceneHierarchyPanel.SetSelectedEntity(m_HoveredEntity);
		}
		return false;
	}
	
	// 新建场景
	void EditorLayer::NewScene()
	{
		m_ActiveScene = CreateRef<Scene>();
		m_ActiveScene->OnViewportResize((uint32_t)m_ViewportSize.x, (uint32_t)m_ViewportSize.y);
		m_SceneHierarchyPanel.SetContext(m_ActiveScene);
	}

	// 打开场景文件
	void EditorLayer::OpenScene()
	{
		std::string filepath = FileDialogs::OpenFile("Kuadu Scene (*.kuadu)\0*.kuadu\0");
		if (!filepath.empty())
			OpenScene(filepath);
	}
	void EditorLayer::OpenScene(const std::filesystem::path& path)
	{
		m_ActiveScene = CreateRef<Scene>();
		m_ActiveScene->OnViewportResize((uint32_t)m_ViewportSize.x, (uint32_t)m_ViewportSize.y);
		m_SceneHierarchyPanel.SetContext(m_ActiveScene);

		SceneSerializer serializer(m_ActiveScene);
		serializer.Deserialize(path.string());
	}

	// 场景保存为...
	void EditorLayer::SaveSceneAs()
	{
		std::string filepath = FileDialogs::SaveFile("Kuadu Scene (*.kuadu)\0*.kuadu\0");
		if (!filepath.empty())
		{
			SceneSerializer serializer(m_ActiveScene);
			serializer.Serialize(filepath);
		}
	}
	
}